#pragma once

#include <iostream>
#include <functional>
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <string.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include "tcp_err.hpp"

namespace ns_server
{
    using func_t = std::function<std::string(const std::string&)>;
    static const uint16_t typeport = 8081;
    static const int backlog = 32;
    
    class tcpServer;
    class ThreadData
    {
        public:
            ThreadData(int sock, const std::string clientip, const uint16_t clientport, tcpServer* tsvr)
            :_sock(sock)
            ,_clientip(clientip)
            ,_clientport(clientport)
            ,_tsvr(tsvr)
            {

            }
        public:
            int _sock;
            std::string _clientip;
            uint16_t _clientport;
            tcpServer* _tsvr;
    };
    class tcpServer
    {
        

    public:
        tcpServer(func_t func, uint16_t port = typeport, bool quit = true)
            :func_(func)
            ,port_(port)
            ,quit_(quit)
        {
            

        }

        void service_v1(int sock, const std::string& clientIP, const uint16_t clientPort)
        {
            char buffer[1024];

            while(true)
            {
                ssize_t s = read(sock, buffer, sizeof(buffer)-1);
                if(s > 0)
                {
                    buffer[s] = 0;
                    std::string message = func_(buffer);
                    std::cout << clientIP << "-" << clientPort << " >> " << message << std::endl;

                    write(sock, message.c_str(), message.size());
                }
                else if(s == 0)
                {
                    close(sock);
                    std::cout << "客户端：" << clientIP << "-" << clientPort << " 关闭了连接！" << std::endl;
                    break;
                }
                else 
                {
                    close(sock);
                    std::cerr << "读取失败！" << strerror(errno) << std::endl;
                    break;
                }
            }
        }

        

        void initServer()
        {
            //1.创建套接字
            listensock_ = socket(AF_INET, SOCK_STREAM, 0);
            if(listensock_ < 0)
            {
                std::cout << "套接字创建失败！" << std::endl;
                exit(SOCK_ERR);
            }

            //2.绑定
            struct sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(port_);
            local.sin_addr.s_addr = INADDR_ANY;

            if(bind(listensock_, (struct sockaddr*)&local, sizeof(local)) < 0)
            {
                std::cout << "绑定失败！" << std::endl;
                exit(BIND_ERR);
            }

            //3.监听
            if(listen(listensock_, backlog) < 0)
            {
                std::cout << "监听失败！" << std:: endl;
                exit(LISTEN_ERR);
            }
           
        }

        static void* threadRoutine(void* args)
        {
            pthread_detach(pthread_self());
            ThreadData* td = static_cast<ThreadData*>(args);
            td->_tsvr->service_v1(td->_sock, td->_clientip, td->_clientport);

            delete td;
            return nullptr;

        }

        void Start()
        {
            //signal(SIGCHLD, SIG_IGN);//最简单

            quit_ = false;
            while(!quit_)
            {
                //4.获取链接，accept
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int sock = accept(listensock_, (struct sockaddr*)&client, &len);
                if(sock < 0)
                {
                    std::cout << "获取连接失败！" << std::endl;
                    continue;
                }

                std::string clientIP = inet_ntoa(client.sin_addr);
                uint16_t clientPort = ntohs(client.sin_port);

                std::cout << "获取连接成功！sock = " << sock << "  listensock_ = " << listensock_ << std::endl;

                //v1
                //service_v1(sock, clientIP, clientPort);


                //v2
                // pid_t id = fork();
                // if(id == 0)//子进程
                // {
                //     close(listensock_);

                //     if(fork() > 0) exit(0);

                //     service_v1(sock, clientIP, clientPort);


                //     exit(0);
                // }
                // else if(id < 0)//创建失败
                // {
                //     close(sock);
                //     continue;
                // }
                // //父进程

                // close(sock);

                // pid_t ret = waitpid(id, nullptr, 0);
                // if(ret == id)
                // {
                //     std::cout << "wait child: " << ret << " success!" << std::endl;
                // }

                //v3多线程
                ThreadData* args = new ThreadData(sock, clientIP, clientPort, this);
                pthread_t tid;
                int n = pthread_create(&tid, nullptr, threadRoutine, args);



                
            }
        }

        ~tcpServer()
        {
        }

    private:
        uint16_t port_;
        int listensock_;
        bool quit_;
        func_t func_;
    };
}